<?php
/*
* StiPHPcms, A web Content management System made with PHP/MySQL
* JordSti : jord52@gmail.com
* Version : 0.0.2
*
* Copyright (C) 2009  jord52@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

require_once("core/sti_html.php");

class Config {
	public $sql_server; //MySQL server
	public $sql_user; //MySQL username
	public $sql_pass; //MySQL password
	public $sql_db; //MySQL Database
	public $sql_prefix; //MySQL Table Prefix

	public $sitename; //Name of the site
	public $isOpen;
	public $closedMessage;
	
	public $keepPageStats;
	
	public $authkey;
	public $external_url;
	public $ssl_mode;
	
	public $use_email_activation;
	public $use_pearmail;
	
}

require_once("core/config.php");

class CMSPage {
	private $initDone;
	private $config;
	private $sql_query_count;
	private $exe_count;
	private $start_mt;
	private $menu;
	private $navbar;
	private $langList;
	private $sessionTimeOut;
	public $cms_version;
	public $cms_stiurl;
	public $numeric_version;
	public $settings;
	public $lang;
	public $exe_ms;
	public $u_online;
	public $template;

	public function __construct($config)
	{
		$this->config = $config;
		$this->sql_query_count = 0;
		$this->langList = array();
		$this->start_mt = microtime();
		$this->initDone = false;
		$this->cms_stiurl = "http://stiphpcms.dynalias.net";
		$this->cms_version = '0.0.2r70';
		$this->numeric_version = 70;
		$this->sessionTimeOut = (((60*60)*24)*5); //Delete session when the last timestamp is from 5 days
	}

	public function sql_query($sql){
		$this->sql_query_count++;
		$sql = $this->replacePrefix($sql);
		$dt = mysql_query($sql)or die($this->sql_error(mysql_error()));
		return $dt;
	}
	
	public function sql_error($mysql_error)
	{
		$sql_log = "cache/sql_error.log";
		
		if(!file_exists($sql_log))
		{
			$fp = fopen($sql_log,'a');
			fwrite($fp,"# StiPHPcms SQL Log file\n");
			fclose($fp);
			chmod($sql_log,0755);
		}
		
		$fp = fopen($sql_log,'a');
		
		$date = date('d/m/Y H:i:s');
		$mysql_error = addslashes($mysql_error);
		
		fwrite($fp,$date." - SQL Error : ".$mysql_error."\n");
		
		fclose($fp);
		
		$this->error($mysql_error);
	}
	
	private function writeToLog($text)
	{
		$main_log = "cache/main.log";
		
		if(!file_exists($main_log))
		{
			$fp = fopen($main_log,'a');
			fwrite($fp,"# StiPHPcms main log file \n");
			fclose($fp);
			chmod($main_log,0755);
		}
		
		$fp = fopen($main_log,'a');

		if(substr($text,strlen($text)-1)=='\n')
		{
			fwrite($text);
		}
		else
		{
			fwrite($text.'\n');
		}
		fclose($fp);
	}
	

	public function loadStiCodeScript()
	{
		$this->template->addHTML('<script type="text/javascript" src="core/tools/sticode.js"></script>');
	}
	
	public function init()
	{
		session_start();
		
		if(!$this->config->isOpen)
		{
			exit($this->config->closedMessage);
		}
		
		if(!mysql_connect($this->config->sql_server,$this->config->sql_user,$this->config->sql_pass))
		{
			exit('The MySQL server doesn\'t answer, try again later');
		}
		mysql_select_db($this->config->sql_db);

		$this->retrieveSettings();
		$this->logvisit();

		include 'themes/'.$this->settings['theme'].'.stm';
	
		$this->template = $template;
		
		$this->loadLangList();
		
		$this->chooseLangFile();

		$this->navbar = $this->retrieveNavBar();
		$this->menu = $this->retrieveMenu();
		
		if($this->isUserLog())
		{
			$key = $this->lang['my_account'];
			$this->navbar['__'.$key] = "myaccount.php";
			
			$key = $this->lang['sign_out'];
			$this->navbar['__'.$key] = "logout.php";
		}
		else
		{
			$key = $this->lang['sign_in'];
			$this->navbar[$key] = "login.php";		
		}
		
		$this->initDone = true;
		
		if($this->config->ssl_mode)
		{
			$this->ssl_only();
		}
		
	}
	
	public function sql_init()
	{

		if(!mysql_connect($this->config->sql_server,$this->config->sql_user,$this->config->sql_pass))
		{
			exit('The MySQL server doesn\'t answer, try again later');
		}
		
		mysql_select_db($this->config->sql_db);

		$this->retrieveSettings();

		
		if($this->config->ssl_mode)
		{
			$this->ssl_only();
		}
	}
	
	
	public function initLess()
	{
		session_start();
		
		if(!$this->config->isOpen)
		{
			exit('Website is not available at the moment...');
		}
		
		if(!mysql_connect($this->config->sql_server,$this->config->sql_user,$this->config->sql_pass))
		{
			exit('The MySQL server doesn\'t answer, try again later');
		}
		
		mysql_select_db($this->config->sql_db);

		
		$this->retrieveSettings();
		//$this->logvisit();
		
		include 'themes/'.$this->settings['theme'].'.stm';

		$this->template = $template;

		$this->loadLangList();
		$this->chooseLangFile();
		
		//$this->navbar = $this->retrieveNavBar();
		//$this->menu = $this->retrieveMenu();
		
		$this->initDone = true;
		
		if($this->config->ssl_mode)
		{
			$this->ssl_only();
		}
	}
	
	private function ssl_only()
	{
		if(isset($_SERVER['HTTPS']))
		{
			if($_SERVER['HTTPS']!='on')
			{
				$this->error($this->lang['ssl_error']);
			}
		}
		else
		{
			$this->error($this->lang['ssl_error']);
		}

	}
	
	private function keepSessionStats($table_array)
	{
		$sess_data = unserialize($table_array['session_data']);
		$user_id = $table_array['user_id'];
		$sess_id = $table_array['session_id'];
		$sess_int = $table_array['id'];
		
		if(isset($_SERVER['REMOTE_HOST']))
		{
			$remote = $_SERVER['REMOTE_HOST'];
		}
		else
		{
			$remote = 'local';
		}

		$ip = $table_array['ip'];
		$timestamp = $table_array['timestamp'];
		$first_timestamp = $table_array['first_timestamp'];
		
				
		$to_file = $user_id.'_'.dechex($first_timestamp);
				
		if(!is_dir('cache/stats'))
		{
			mkdir('cache/stats',0777);
			$fp = fopen('cache/stats/index.php','w');
			fwrite($fp,'<?php exit(); ?>');
			fclose($fp);
		}
				
		if(file_exists($to_file))
		{
			$to_file .= '_'.dechex(rand(1024,1024*16));
		}
				
		$fp = fopen('cache/stats/'.$to_file,'w');
		fwrite($fp,"session_id=".$sess_id.";\nsession_int=".$sess_int.";\nip=".$ip.";\n");
		fwrite($fp,"remote_host=".$remote.";\n");
		fwrite($fp,"first_timestamp=".$first_timestamp.";\n");
		fwrite($fp,"last_timestamp=".$timestamp.";\n");
		for($i=0; $i<count($sess_data['history']); $i++)
		{
			fwrite($fp,"uri_".$i."=".$sess_data['history'][$i].";\n");
		}
		for($i=0; $i<count($sess_data['user_agent']); $i++)
		{
			fwrite($fp,"useragent_".$i."=".$sess_data['user_agent'][$i].";\n");
		}
		fclose($fp);
		
		chmod('cache/stats/'.$to_file,0777);
	}
	
	private function clearSessionTimeOut()
	{
		$timeout = time()-$this->sessionTimeOut;	
		
		if($this->config->keepPageStats)
		{
			$dt = $this->sql_query("SELECT * FROM %prefix%session WHERE timestamp<$timeout");
			while($data=mysql_fetch_array($dt))
			{
				$this->keepSessionStats($data);
			}
		}
		
		$this->sql_query("DELETE FROM %prefix%session WHERE timestamp<$timeout");

	}
	
	private function chooseLangFile()
	{
		$isIncluded = false;
		
		$default_lang = $this->settings['lang'];
		
		if(isset($_SESSION['user_lang']))
		{
			$user_lang = $_SESSION['user_lang'];
		}
		
		if(isset($_GET['lang']))
		{
			$user_lang = $_GET['lang'];
		}
		
		if(isset($user_lang))
		{
			foreach($this->langList as $id => $file)
			{
				if($user_lang==$id)
				{
					$isIncluded = true;
					include 'core/lang/'.$file;
					$this->lang = $lang;
					
					$_SESSION['user_lang'] = $id;	
				}
			}
		}

		if(!$isIncluded)
		{
			include 'core/lang/'.$default_lang.'.php';
			$this->lang = $lang;
		}
	
	}
	
	private function loadLangList()
	{
		if(file_exists("cache/lang.sti"))
		{
			$fp = fopen('cache/lang.sti','r');
			$data = '';
			while($line = fgets($fp))
			{
				$data .= $line;
			}
			fclose($fp);
			$this->langList = unserialize($data);
		}
		else
		{
			$this->createLangList();
			$this->loadLangList();	
		}
	}
	
	private function createLangList()
	{
		$fp = fopen('cache/lang.sti','w');
		
		$data = array('en' => 'en.php','fr' => 'fr.php');
		
		fwrite($fp,serialize($data));
		
		fclose($fp);
	}
	
	public function addLangFile($lang_key,$file)
	{
		if(!array_key_exists($lang_key,$file))
		{
			$this->langList[$lang_key] = $file;
			
			$this->saveLangFist();
		}
	}
	
	private function saveLangList()
	{
		$fp = fopen('cache/lang.sti','w');
		
		$data = serialize($this->langList);
		
		fwrite($fp,$data);
		
		fclose($fp);
	}
	
	public function getExternalUrl()
	{
		
		return $this->config->external_url;
	}
	
	public function error($msg,$refreshUrl = "none")
	{
		if(!$this->initDone)
		{
			$this->init();
		}
		
		
		if($refreshUrl == "none")
		{
			$this->renderHeader($this->lang['error']);
		}
		else
		{
			$this->renderHeader($this->lang['error'],true,$refreshUrl);
		}
		
		$this->template->setError($this->lang['error'],$msg);
		
		echo $this->template->render();
		exit;
	}
	
	public function initModule()
	{
		$this->init();
		
		if(isset($_GET['mod']))
		{
			$this->moduleLoader($_GET['mod']);
		}
		else
		{
			$this->error($this->lang['no_module_spec']);
		}
	}
	
	public function initAdminModule()
	{
		$this->init();
		
		$this->addMenuEntry('__'.$this->lang['admin_menu_title'],"MENUTAB");
		$this->addMenuEntry('__'.$this->lang['admin_users'],"admin.php?t=users");
		$this->addMenuEntry('__'.$this->lang['admin_settings'],"admin.php?t=settings");
		$this->addMenuEntry('__'.$this->lang['menu'],"admin.php?t=menu");
		$this->addMenuEntry('__'.$this->lang['pages'],"admin.php?t=pages");
		$this->addMenuEntry('__'.$this->lang['navbar'],"admin.php?t=navbar");
		$this->addMenuEntry('__'.$this->lang['rank'],"admin.php?t=rank");
		
		$dt = $this->sql_query("SELECT * FROM %prefix%modules WHERE admin_module=1");
		
		$this->addMenuEntry("___#Modules","MENUTAB");
		
		while($data = mysql_fetch_array($dt))
		{
			$name = $data['name'];
			$name = strtoupper(substr($name,0,1)).substr($name,1);
			$this->addMenuEntry('__'.$name,'admin.php?mod='.$data['name']);
		}
		
		if(isset($_GET['mod']))
		{
			$this->adminModuleLoader($_GET['mod']);
		}
		else
		{
			$this->adminModuleLoader();
		}
	}

	public function renderHeader($title,$refresh = false,$refreshUrl = "")
	{
		$css = 'themes/'.$this->settings['theme'].'.css';
		$title =$this->config->sitename.' - '.$title;
		$head = new HTMLHeader($title,$css,$this->settings['meta_keywords'],$this->settings['meta_description'],$refresh,$refreshUrl);
		echo $head->render();
	}

	public function renderMenu()
	{
		$this->template->setNavLink($this->navbar);
		$this->template->setMenu($this->menu);
	}

	private function retrieveMenu()
	{
		$rank_id = $this->getUserRank();

		$dt = $this->sql_query("SELECT * FROM %prefix%menu WHERE rank_req<=$rank_id ORDER BY zindex");
		$menu = array();
		while($data = mysql_fetch_array($dt))
		{
			$lname = $data['lname'];
			$menu[$lname] = $data['url'];
		}

		return $menu;
	}

	private function retrieveNavBar()
	{
		$rank_id = $this->getUserRank();

		$dt = $this->sql_query("SELECT * FROM %prefix%navbar WHERE rank_req<=$rank_id ORDER BY zindex");
		$navbar = array();
		while($data = mysql_fetch_array($dt))
		{
			$lname = $data['lname'];
			$navbar[$lname] = $data['url'];
		}

		return $navbar;
	}

	private function logvisit()
	{
		require_once("core/tools/cfgStream.php");
		$this->clearSessionTimeOut();
		$ip = $_SERVER['REMOTE_ADDR'];
		$scriptname = $_SERVER['SCRIPT_NAME'];
		$uri = $_SERVER['REQUEST_URI'];
		$useragent = $_SERVER['HTTP_USER_AGENT'];
		$filename = $_SERVER['SCRIPT_FILENAME'];
		$timestamp = time();
		
		
		$time_start = $timestamp - 60;
		$time_end = $timestamp + 60;
		
		if($this->isUserLog())
		{
			$uid = $_SESSION['user_id'];
		}
		else
		{
			$uid = -1;
		}
		
		if(isset($_SESSION['user_agent']))
		{
			if(!in_array($useragent,$_SESSION['user_agent']))
			{
				$_SESSION['user_agent'][] = $useragent;
			}
		}
		else
		{
			$_SESSION['user_agent'] = array();
			$_SESSION['user_agent'][] = $useragent;
		}
		
		if(isset($_SESSION['history']))
		{
			$_SESSION['history'][] = $uri;
		}
		else
		{
			$_SESSION['history'] = array();
			$_SESSION['history'][] = $uri;
		}

		//$this->sql_query("INSERT INTO %prefix%visitlog VALUES('','$useragent','$scriptname','$uri','$ip','$uid','$filename',$timestamp)");

		//$dt = $this->sql_query("SELECT * FROM %prefix%visitlog WHERE filename='$filename'");
		
		//$this->exe_count = mysql_num_rows($dt);
		
		$counter = new cfgStream('cache/page_counter','int');
		
		if($counter->isVariableExist($uri))
		{
			$counter->entry[$uri] += 1;
		}
		else
		{
			$counter->addVariable($uri,1);
		}
		
		$this->exe_count = $counter->entry[$uri];
		
		$counter->save();
		
		$session_id = session_id();
		
		$dt = $this->sql_query("SELECT * FROM %prefix%session WHERE session_id='$session_id'");
		
		if(mysql_num_rows($dt)==0)
		{
			$sess_data = serialize($_SESSION);
			$this->sql_query("INSERT INTO %prefix%session VALUES('','$ip',$uid,'$session_id','$sess_data',$timestamp,$timestamp)");
		}
		else if(mysql_num_rows($dt)==1)
		{
			$data = mysql_fetch_array($dt);
			$s_id = $data['id'];
			$sess_data = serialize($_SESSION);
			$this->sql_query("UPDATE %prefix%session SET user_id=$uid,session_data='$sess_data',timestamp=$timestamp WHERE id=$s_id");
		}
		
		$dt = $this->sql_query("SELECT * FROM %prefix%session WHERE timestamp BETWEEN $time_start AND $time_end");
		$this->u_online = mysql_num_rows($dt);
		
		
	}

	public function logUser($username,$pass_hash)
	{
		$this->initLess();
		$username = mysql_real_escape_string($username);
		$dt = $this->sql_query("SELECT * FROM %prefix%users WHERE username='$username'");
		
		if(mysql_num_rows($dt)==0)
		{
			$this->error($this->lang['user_auth_error']);
		}
		else
		{
			$data = mysql_fetch_array($dt);
			$pass_db = $data['password'];
			
			if($pass_db!=$pass_hash)
			{
				$this->error($this->lang['user_auth_error']);
			}
			else
			{
				
				if($data['rank']==0)
				{
					$this->error($this->lang['account_not_active']);	
				}
				
				/*session_register('AUTH_KEY');
				session_register('username');
				session_register('pass_hash');
				session_register('user_id');
				session_register('user_rank');*/
				
				$_SESSION['AUTH_KEY'] = $this->config->authkey;
				$_SESSION['username'] = $data['username'];
				$_SESSION['pass_hash'] = $pass_hash;
				$_SESSION['user_id'] = $data['id'];
				$_SESSION['user_rank'] = $data['rank'];
				
				header('location: index.php');
			}
		}
	}
	
	public function logOut()
	{
		$this->initLess();
		
		$session_id = session_id();
		
		$dt = $this->sql_query("SELECT * FROM %prefix%session WHERE session_id='$session_id'");
		
		$data = mysql_fetch_array($dt);
		
		$this->keepSessionStats($data);
		
		$this->sql_query("DELETE FROM %prefix%session WHERE session_id='$session_id'");
		session_regenerate_id(true);
		session_destroy();
		header('location: index.php');
	}
	
	private function retrieveSettings(){
		$dt = $this->sql_query("SELECT * FROM %prefix%settings");
		$this->settings = array();
		while($data = mysql_fetch_array($dt))
		{
			$varname = $data['varname'];
			$this->settings[$varname] = $data['value'];
		}
	}

	public function isUserLog(){
		if(isset($_SESSION['AUTH_KEY']))
		{
			if($_SESSION['AUTH_KEY']==$this->config->authkey)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
	
	public function isAdmin()
	{
		if($this->isUserLog() && $this->initDone)
		{
			if($this->getUserRank()>=$this->settings['admin_rank'])
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
	
	public function adminOnly()
	{
		if(!$this->isAdmin())
		{
			$this->error($this->lang['right_error']);
		}
	}

	public function getUserRank()
	{
		if($this->isUserLog())
		{
			return $_SESSION['user_rank'];
		}
		else
		{
			return 0;
		}
	}
	
	public function getUserId()
	{
		if($this->isUserLog())
		{
			return $_SESSION['user_id'];
		}
		else
		{
			return 0;
		}
	}
	
	public function addFrame($title,$text)
	{
		$this->template->addFrame($title,$text);
	}
	
	private function renderFooter()
	{
		$footer = $this->settings['footertext'].'<br /><span class="sticopyright"><a href="'.$this->cms_stiurl.'" target="_blank">Powered By StiPHPcms '.$this->cms_version.'</a></span>';
		$year = date('Y');
		$footer = str_replace('%site',$this->config->sitename,$footer);
		$footer = str_replace('%year',$year,$footer);
		$footer = str_replace('%sql_c',$this->sql_query_count,$footer);
		$footer = str_replace('%c',$this->exe_count,$footer);
		$footer = str_replace('%o',$this->u_online,$footer);
		$footer = str_replace('%exe_ms',round($this->exe_ms,5),$footer);
		
		$this->template->setFooterText($footer);
		
	}
	
	public function moduleLoader($name)
	{
		$name = mysql_real_escape_string($name);
		$dt = $this->sql_query("SELECT * FROM %prefix%modules WHERE name='$name'");
		
		if(mysql_num_rows($dt)==0)
		{
			$this->error($this->lang['module_not_found']);
		}
		else
		{
			$data = mysql_fetch_array($dt);
			include "modules/".$data['classfile'];
			
			$module = new Module($this);
			$module->run();
		}
		
	}
	
	public function adminModuleLoader($name = "main")
	{
		$this->adminOnly();
		
		if($name=="main")
		{
			include "modules/main.php";
			$module = new AdminModule($this);
			$module->run();
		}
		else
		{
			$dt = $this->sql_query("SELECT * FROM %prefix%modules WHERE name='$name'");
			if(mysql_num_rows($dt)==0)
			{
				$this->error($this->lang['module_not_found']);
			}
			else
			{
				$data = mysql_fetch_array($dt);
				include "modules/".$data['classfile'];
			
				$module = new AdminModule($this);
				$module->run();
			}
		}
	}
	
	public function addSetting($name,$value = "default")
	{
		if(!array_key_exists($name,$this->settings))
		{
			$this->sql_query("INSERT INTO %prefix%settings VALUES('','$name','$value')");
			$this->settings[$name] = $value;
		}
	}
	
	public function isSettingExist($name)
	{
		if(array_key_exists($name,$this->settings))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	public function addLangEntry($name,$value)
	{
		if(!array_key_exists($name,$this->lang))
		{
			$this->lang[$name] = $value;
		}
	}
	
	public function addMenuEntry($name,$link)
	{
		if(!array_key_exists($name,$this->menu))
		{
		$this->menu[$name] = $link;
		}
	}
	
	public function saveLangFile($lang_key = 'en')
	{
		$fp = fopen('core/lang/'.$lang_key.'.php','w');
		
		fwrite($fp,'<?php 
		$lang = array(');
		foreach($this->lang as $key => $value)
		{
			$value = addslashes($value);
			fwrite($fp,"'$key' => '$value',
			");
		}
		fwrite($fp,');
		?>');
		fclose($fp);
	}
	
	private function replacePrefix($query)
	{
		$query = str_replace("%prefix%",$this->config->sql_prefix,$query);
		return $query;
	}
	
	public function close()
	{
		$this->template->renderContent();
		$this->exe_ms = microtime() - $this->start_mt;
		$this->renderFooter();
		echo $this->template->render();
	}
	
}

?>